#ifndef _DELEGATE_H
#define _DELEGATE_H


///////////////////////////////////////////////////////////////////////////
//																		 //
//	Author:		Michael Mozdzierz										 //
//	Date:		10/17/2014												 //
//	Purpose:	Prototype a delegate									 //
//																		 //
///////////////////////////////////////////////////////////////////////////
#include "Functor.h"
#include <vector>

using namespace std;

template<typename T>
struct Delegate
{
	vector<Functor<T>> subscribers;
	Delegate(void);
	~Delegate(void);
	Delegate(Delegate<T>&);

	///////////////////////////////////////////////////////////////////////
	// Invoke all the functions subcribed to this event
	void operator()(void** prams);

	// Invoke all the functions subcribed to this event
	void Invoke(void** prams);

	// subscribe to this event
	void Subscribe(Functor<T> function);
};


///////////////////////////////////////////////////////////////////////
// Subscribe to this function
template<typename T>
void operator +=(Delegate<T>& d, Functor<T>& function)
{
	d.subscribers.push_back(function);
}
///////////////////////////////////////////////////////////////////////
// Unsubscribe to this function
template<typename T>
void operator-=(Delegate<T>& d, Functor<T>& function)
{

	for (unsigned int i = 0; i < subscribers.size(); i++)
		if (subscribers[i] == function)
			subscribers.erase(subscribers.first() + i);
}

template<typename T>
Delegate<T>::Delegate(void)
{

}
template<typename T>
Delegate<T>::~Delegate(void)
{
}

template<typename T>
Delegate<T>::Delegate(Delegate<T>& other)
{
	for (unsigned int i = 0; i < other.subscribers.size(); i++)
		subscribers.push_back(other[i]);
}

template<typename T>
void Delegate<T>::operator()(void** prams)
{
	Invoke(prams);
}

template<typename T>
void Delegate<T>::Subscribe(Functor<T> function)
{
	subscribers.push_back(function);
}

template<typename T>
void Delegate<T>::Invoke(void** prams)
{
	for (unsigned int i = 0; i < subscribers.size(); i++)
		subscribers[i](prams);
}
#endif